package com.szadst.szoemhost_and_adst_v3;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Arrays;

import com.szadst.szoemhost_lib.DevComm;
import com.szadst.szoemhost_lib.HostLib;
import com.szadst.szoemhost_lib.IFPListener;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    // control variables
    Button m_btnOpenDevice;
    Button m_btnCloseDevice;
    Button m_btnEnroll;
    Button m_btnVerify;
    Button m_btnIdentify;
    Button m_btnIdentifyFree;
    Button m_btnCaptureImage;
    Button m_btnCancel;
    Button m_btnGetUserCount;
    Button m_btnGetEmptyID;
    Button m_btnDeleteID;
    Button m_btnDeleteAll;
    Button m_btnReadTemplate;
    Button m_btnWriteTemplate;
    Button m_btnGetFWVer;
    Button m_btnSetDevPass;
    Button m_btnVerifyPass;
    Button m_btnVerifyImage;
    Button m_btnIdentifyImage;
    Button m_btnGetFeatureOfFP;
    EditText m_editUserID;
    EditText m_editDevPassword;
    TextView m_txtStatus;
    ImageView m_FpImageViewer;
    Spinner m_spBaudrate;
    Spinner m_spDevice;

    // member variables
    int m_nBaudrate;
    String m_szDevice;
    int m_nUserID;
    String m_strPost;

    byte[] m_binImage, m_bmpImage;
    int m_nImgWidth, m_nImgHeight;
    byte[] m_TemplateData;
    int m_nTemplateSize = 0;

    boolean m_bForce = false;//是否按压？

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // set keep screen on
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

        // initialize widget
        InitWidget();
        SetInitialState();
        m_spBaudrate.setSelection(4);

        // allocate image buffer
        m_binImage = new byte[1024 * 100];
        m_bmpImage = new byte[1024 * 100];
        m_TemplateData = new byte[DevComm.SZ_MAX_RECORD_SIZE];

        // get device list
        HostLib.getInstance(this).FPCmdProc().GetDeviceList(m_spDevice);

        // set listener
        //设置监听
        HostLib.getInstance(this).FPCmdProc().SetListener(new IFPListener.FPCommandListener() {
            @Override
            public void cmdProcReturn(int p_nCmdCode, int p_nRetCode, int p_nParam1, int p_nParam2) { // command process result
                ProcResponsePacket(p_nCmdCode, p_nRetCode, p_nParam1, p_nParam2);
            }

            @Override
            public void cmdProcReturnData(byte[] p_pData, int p_nSize) { // command process data result获取返回数据
                int i;
                if (p_nSize > DevComm.SZ_MAX_RECORD_SIZE) {
                    System.arraycopy(p_pData, 0, m_binImage, 0, p_nSize);
                    m_nImgWidth = DevComm.SZ_IMG_WIDTH;
                    m_nImgHeight = DevComm.SZ_IMG_HEIGHT;
                } else {
                    System.arraycopy(p_pData, 0, m_TemplateData, 0, p_nSize);
                    m_nTemplateSize = p_nSize;
                }
            }

            @Override
            public void cmdProcShowText(String p_szInfo) { // show information
                m_txtStatus.setText(p_szInfo);
            }
        }, new IFPListener.FPCancelListener() {
            @Override
            public void cancelReturn(int p_nRetCode) { // cancel result
                EnableCtrl(true);
            }
        });

        // baudrate selector
        m_spBaudrate.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                if (position == 0)
                    m_nBaudrate = 9600;
                else if (position == 1)
                    m_nBaudrate = 19200;
                else if (position == 2)
                    m_nBaudrate = 38400;
                else if (position == 3)
                    m_nBaudrate = 57600;
                else// if (position == 4)
                    m_nBaudrate = 115200;
            }

            public void onNothingSelected(AdapterView<?> parent) {
            }
        });

        m_spDevice.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                m_szDevice = m_spDevice.getItemAtPosition(position).toString();
            }

            public void onNothingSelected(AdapterView<?> parent) {
            }
        });
    }

    public void onClick(View view) {
        if (view == m_btnOpenDevice)
            OnOpenDeviceBtn();
        else if (view == m_btnCloseDevice)
            OnCloseDeviceBtn();
        else if (view == m_btnCancel)
            OnCancelBtn();
        else if (view == m_btnEnroll)
            OnEnrollBtn();
        else if (view == m_btnVerify)
            OnVerifyBtn();
        else if (view == m_btnIdentify)
            OnIdentifyBtn();
        else if (view == m_btnIdentifyFree)
            OnIdentifyFreeBtn();
        else if (view == m_btnGetEmptyID)
            OnGetEmptyID();
        else if (view == m_btnGetUserCount)
            OnGetUserCount();
        else if (view == m_btnDeleteID)
            OnDeleteIDBtn();
        else if (view == m_btnDeleteAll)
            OnDeleteAllBtn();
        else if (view == m_btnReadTemplate)
            OnReadTemplateBtn();
        else if (view == m_btnWriteTemplate)
            OnWriteTemplateBtn();
        else if (view == m_btnCaptureImage)
            OnUpImage();
        else if (view == m_btnGetFWVer)
            OnGetFwVersion();
        else if (view == m_btnSetDevPass)
            OnSetDevPass();
        else if (view == m_btnVerifyPass)
            OnVerifyPassBtn();
        else if (view == m_btnVerifyImage)
            OnVerifyWithImage();
        else if (view == m_btnIdentifyImage)
            OnIdentifyWithImage();
        else if (view == m_btnGetFeatureOfFP)
            OnGetFeatureOfCapturedFP();
    }

    public void InitWidget() {
        m_FpImageViewer = findViewById(R.id.ivImageViewer);
        m_btnOpenDevice = findViewById(R.id.btnOpenDevice);
        m_btnCloseDevice = findViewById(R.id.btnCloseDevice);
        m_btnEnroll = findViewById(R.id.btnEnroll);
        m_btnVerify = findViewById(R.id.btnVerify);
        m_btnIdentify = findViewById(R.id.btnIdentify);
        m_btnIdentifyFree = findViewById(R.id.btnIdentifyFree);
        m_btnCaptureImage = findViewById(R.id.btnCaptureImage);
        m_btnCancel = findViewById(R.id.btnCancel);
        m_btnGetUserCount = findViewById(R.id.btnGetEnrollCount);
        m_btnGetEmptyID = findViewById(R.id.btnGetEmptyID);
        m_btnDeleteID = findViewById(R.id.btnRemoveTemplate);
        m_btnDeleteAll = findViewById(R.id.btnRemoveAll);
        m_btnReadTemplate = findViewById(R.id.btnReadTemplate);
        m_btnWriteTemplate = findViewById(R.id.btnWriteTemplate);
        m_btnGetFWVer = findViewById(R.id.btnGetFWVer);
        m_btnSetDevPass = findViewById(R.id.btnSetDevPass);
        m_btnVerifyPass = findViewById(R.id.btnVerifyPass);
        m_btnVerifyImage = findViewById(R.id.btnVerifyImage);
        m_btnIdentifyImage = findViewById(R.id.btnIdentifyImage);
        m_btnGetFeatureOfFP = findViewById(R.id.btnGetFeatureOfCapturedFP);
        m_txtStatus = findViewById(R.id.txtStatus);
        m_editUserID = findViewById(R.id.editUserID);
        m_editDevPassword = findViewById(R.id.editDevPassword);
        m_spBaudrate = findViewById(R.id.spnBaudrate);
        m_spDevice = findViewById(R.id.spnDevice);

        m_btnOpenDevice.setOnClickListener(this);
        m_btnCloseDevice.setOnClickListener(this);
        m_btnEnroll.setOnClickListener(this);
        m_btnVerify.setOnClickListener(this);
        m_btnIdentify.setOnClickListener(this);
        m_btnIdentifyFree.setOnClickListener(this);
        m_btnCaptureImage.setOnClickListener(this);
        m_btnCancel.setOnClickListener(this);
        m_btnGetUserCount.setOnClickListener(this);
        m_btnGetEmptyID.setOnClickListener(this);
        m_btnDeleteID.setOnClickListener(this);
        m_btnDeleteAll.setOnClickListener(this);
        m_btnReadTemplate.setOnClickListener(this);
        m_btnWriteTemplate.setOnClickListener(this);
        m_btnGetFWVer.setOnClickListener(this);
        m_btnSetDevPass.setOnClickListener(this);
        m_btnVerifyPass.setOnClickListener(this);
        m_btnVerifyImage.setOnClickListener(this);
        m_btnIdentifyImage.setOnClickListener(this);
        m_btnGetFeatureOfFP.setOnClickListener(this);
    }

    public void EnableCtrl(boolean bEnable) {
        m_btnCloseDevice.setEnabled(bEnable);
        m_btnCancel.setEnabled(!bEnable);
        m_btnEnroll.setEnabled(bEnable);
        m_btnVerify.setEnabled(bEnable);
        m_btnIdentify.setEnabled(bEnable);
        m_btnIdentifyFree.setEnabled(bEnable);
        m_btnGetUserCount.setEnabled(bEnable);
        m_btnGetEmptyID.setEnabled(bEnable);
        m_btnDeleteID.setEnabled(bEnable);
        m_btnDeleteAll.setEnabled(bEnable);
        m_btnReadTemplate.setEnabled(bEnable);
        m_btnWriteTemplate.setEnabled(bEnable);
        m_btnCaptureImage.setEnabled(bEnable);
        m_btnGetFWVer.setEnabled(bEnable);
        m_btnSetDevPass.setEnabled(bEnable);
        m_btnVerifyPass.setEnabled(bEnable);
        m_btnVerifyImage.setEnabled(bEnable);
        m_btnIdentifyImage.setEnabled(bEnable);
        m_btnGetFeatureOfFP.setEnabled(bEnable);

        m_editUserID.setEnabled(bEnable);
        m_editDevPassword.setEnabled(bEnable);
    }

    public void SetInitialState() {
        m_txtStatus.setText("Please open device!");
        EnableCtrl(false);
        m_btnOpenDevice.setEnabled(true);
        m_btnCancel.setEnabled(false);
    }

    public void OnOpenDeviceBtn() { // OPEN button click
        if (HostLib.getInstance(this).FPCmdProc().OpenDevice(m_szDevice, m_nBaudrate) == 0) {
            m_btnOpenDevice.setEnabled(false);
            EnableCtrl(true);
        }
    }

    public void OnCloseDeviceBtn() { // CLOSE button click
        HostLib.getInstance(this).FPCmdProc().CloseDevice();
        SetInitialState();
    }

    public void OnCancelBtn() { // CANCEL button click
        HostLib.getInstance(this).FPCmdProc().Run_CmdCancel();
    }

    public void OnEnrollBtn() { // ENROLL button click
        int w_nTemplateNo;

        w_nTemplateNo = GetInputTemplateNo();
        if (w_nTemplateNo < 0)
            return;

        EnableCtrl(false);
        if (HostLib.getInstance(this).FPCmdProc().Run_CmdEnroll(w_nTemplateNo, m_bForce) != 0) {
            EnableCtrl(true);
        }
    }

    public void OnVerifyBtn() { // VERIFY button click
        int w_nTemplateNo;

        w_nTemplateNo = GetInputTemplateNo();
        if (w_nTemplateNo < 0)
            return;

        EnableCtrl(false);
        if (HostLib.getInstance(this).FPCmdProc().Run_CmdVerify(w_nTemplateNo, m_bForce) != 0) {
            EnableCtrl(true);
        }
    }

    public void OnIdentifyBtn() { // IDENTIFY button click
        EnableCtrl(false);
        if (HostLib.getInstance(this).FPCmdProc().Run_CmdIdentify(m_bForce) != 0) {
            EnableCtrl(true);
        }
    }

    public void OnIdentifyFreeBtn() { // IDENTIFY FREE button click
        EnableCtrl(false);
        if (HostLib.getInstance(this).FPCmdProc().Run_CmdIdentifyFree(m_bForce) != 0) {
            EnableCtrl(true);
        }
    }

    public void OnGetEmptyID() { // GET EMPTY ID button click
        HostLib.getInstance(this).FPCmdProc().Run_CmdGetEmptyID(m_bForce);
    }

    public void OnGetUserCount() { // GET ENROLL COUNT button click
        HostLib.getInstance(this).FPCmdProc().Run_CmdGetUserCount(m_bForce);
    }

    public void OnDeleteIDBtn() { // REMOVE TMPL button click
        int w_nTemplateNo;

        w_nTemplateNo = GetInputTemplateNo();
        if (w_nTemplateNo < 0)
            return;

        HostLib.getInstance(this).FPCmdProc().Run_CmdDeleteID(w_nTemplateNo, m_bForce);
    }

    public void OnDeleteAllBtn() { // REMOVE ALL button click
        HostLib.getInstance(this).FPCmdProc().Run_CmdDeleteAll(m_bForce);
    }

    public void OnReadTemplateBtn() { // READ TEMPLATE button click
        int w_nTemplateNo;

        w_nTemplateNo = GetInputTemplateNo();
        if (w_nTemplateNo < 0)
            return;

        HostLib.getInstance(this).FPCmdProc().Run_CmdReadTemplate(w_nTemplateNo, m_bForce);
    }

    public void OnWriteTemplateBtn() { // WRITE TEMPLATE button click
        int w_nTemplateNo;
        byte[] w_pTemplate = new byte[DevComm.SZ_MAX_RECORD_SIZE];
        int w_nTemplateSize = 0;

        w_nTemplateNo = GetInputTemplateNo();
        if (w_nTemplateNo < 0)
            return;

        // read template
        //ReadTemplateFile(w_nTemplateNo, w_pTemplate);
        w_nTemplateSize = DevComm.SZ_TEMPLATE_SIZE;
        System.arraycopy(m_TemplateData,0,w_pTemplate,0,w_nTemplateSize);
        HostLib.getInstance(this).FPCmdProc().Run_CmdWriteTemplate(w_nTemplateNo, w_pTemplate, w_nTemplateSize, m_bForce);
    }

    public void OnUpImage() { // CAPTURE IMAGE button click
        EnableCtrl(false);
        if (HostLib.getInstance(this).FPCmdProc().Run_CmdUpImage(m_bForce) != 0)
            EnableCtrl(true);
    }

    public void OnGetFwVersion() { // GET FW VERSION button click
        HostLib.getInstance(this).FPCmdProc().Run_CmdGetFwVersion(m_bForce);
    }

    public void OnSetDevPass() { // SET PASSWORD button click
        if (m_editDevPassword.length() != 0 && m_editDevPassword.length() != 14) {
            m_strPost = "Invalid Device Password. \nPlease input valid device password(length=14)!";
            m_txtStatus.setText(m_strPost);
            EnableCtrl(true);
            return;
        }

        HostLib.getInstance(this).FPCmdProc().Run_CmdSetDevPass(m_editDevPassword.getText().toString(), m_bForce);
    }

    public void OnVerifyPassBtn() { // VERIFY PASSWORD button click
        if (m_editDevPassword.length() != 14) {
            m_strPost = "Invalid Device Password. \nPlease input valid device password(length=14)!";
            m_txtStatus.setText(m_strPost);
            EnableCtrl(true);
            return;
        }

        HostLib.getInstance(this).FPCmdProc().Run_CmdVerifyPass(m_editDevPassword.getText().toString(), m_bForce);
    }

    public void OnVerifyWithImage() { // VERIFY IMAGE button click
        int w_nTemplateNo;
        byte[] w_pImage = new byte[DevComm.SZ_IMG_WIDTH * DevComm.SZ_IMG_HEIGHT];
        int w_nWidth, w_nHeight;

        w_nTemplateNo = GetInputTemplateNo();
        if (w_nTemplateNo < 0)
            return;

        // read image
        w_nWidth = DevComm.SZ_IMG_WIDTH;
        w_nHeight = DevComm.SZ_IMG_HEIGHT;
        ReadImage(w_pImage, w_nWidth, w_nHeight);

        HostLib.getInstance(this).FPCmdProc().Run_CmdVerifyWithImage(w_pImage, w_nWidth * w_nHeight, w_nTemplateNo, m_bForce);
    }

    public void OnIdentifyWithImage() { // IDENTIFY IMAGE button click
        byte[] w_pImage = new byte[DevComm.SZ_IMG_WIDTH * DevComm.SZ_IMG_HEIGHT];
        int w_nWidth, w_nHeight;

        // read image
        w_nWidth = DevComm.SZ_IMG_WIDTH;
        w_nHeight = DevComm.SZ_IMG_HEIGHT;
        ReadImage(w_pImage, w_nWidth, w_nHeight);

        HostLib.getInstance(this).FPCmdProc().Run_CmdIdentifyWithImage(w_pImage, w_nWidth * w_nHeight, m_bForce);
    }

    public void OnGetFeatureOfCapturedFP() { // GET FEATURE OF FP button click
        EnableCtrl(false);
        if (HostLib.getInstance(this).FPCmdProc().Run_CmdGetFeatureOfCapturedFP(m_bForce) != 0)
            EnableCtrl(true);
    }

    private int GetInputTemplateNo() {
        String str;

        str = m_editUserID.getText().toString();

        if (str.isEmpty()) {
            m_txtStatus.setText("Please input user id");
            return -1;
        }

        try {
            m_nUserID = Integer.parseInt(str);
        } catch (NumberFormatException e) {
            m_txtStatus.setText(String.format("Please input correct user id(1~%d)", (short) HostLib.getInstance(this).FPDevComm().MAX_RECORD_COUNT));
            return -1;
        }

        return m_nUserID;
    }

    @Override
    public boolean onKeyDown(int KeyCode, KeyEvent event) {
        switch (KeyCode) {
            case KeyEvent.KEYCODE_BACK:
                if (event.getRepeatCount() == 0) {
                    if (m_btnCancel.isEnabled()) {
                        Toast toast = Toast.makeText(getApplicationContext(), "Please cancel your command first", Toast.LENGTH_SHORT);
                        toast.show();
                        return true;
                    }
                    if (m_btnCloseDevice.isEnabled())
                        OnCloseDeviceBtn();
                }
                break;
        }

        return super.onKeyDown(KeyCode, event);
    }

    private boolean ReadTemplateFile(int p_nUserID, byte[] p_pTemplate) {
        // Load Template from (mnt/sdcard/sz_template)
        int w_nLen;
        int i;
        short w_nChkSum = 0;
        short w_nCalcChkSum = 0;

        // Open Template File
        String w_szSaveDirPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/sz_template";
        File w_fpTemplate = new File(w_szSaveDirPath + "/" + String.valueOf(p_nUserID) + ".fpt");
        if (!w_fpTemplate.exists()) {
            // Show Save Path
            m_strPost = "Can't load " + w_szSaveDirPath + "/" + String.valueOf(p_nUserID) + ".fpt";
            return false;
        }

        // Get File Length
        w_nLen = (int) w_fpTemplate.length();
        if (w_nLen > DevComm.SZ_MAX_RECORD_SIZE) {
            m_strPost = "Invalid template file.";
            return false;
        }

        // Load Template Data
        FileInputStream w_fiTemplate = null;
        try {
            w_fiTemplate = new FileInputStream(w_fpTemplate);
            w_fiTemplate.read(p_pTemplate, 0, w_nLen);
            w_fiTemplate.close();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

        // Set Template Length
        if (w_nLen == DevComm.SZ_TEMPLATE_SIZE) {
            for (i = 0; i < w_nLen - 2; i++) {
                w_nChkSum += (p_pTemplate[i] & 0xFF);
            }
            w_nCalcChkSum = HostLib.getInstance(this).FPDevComm().MAKEWORD((byte) p_pTemplate[w_nLen - 2], (byte) p_pTemplate[w_nLen - 1]);
            if (w_nChkSum != w_nCalcChkSum) {
                m_strPost = "Invalid template data.";
                return false;
            }
        }

        return true;
    }

    public boolean WriteTemplateFile(int p_nUserID, byte[] pTemplate, int p_nSize) {
        // Save Template to (mnt/sdcard/sz_template)
        // Create Directory
        String w_szSaveDirPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/sz_template";
        File w_fpDir = new File(w_szSaveDirPath);
        if (!w_fpDir.exists())
            w_fpDir.mkdirs();

        // Create Template File
        File w_fpTemplate = new File(w_szSaveDirPath + "/" + String.valueOf(p_nUserID) + ".fpt");
        if (!w_fpTemplate.exists()) {
            try {
                w_fpTemplate.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
                return false;
            }
        }

        // Save Template Data
        FileOutputStream w_foTemplate = null;
        try {
            w_foTemplate = new FileOutputStream(w_fpTemplate);
            w_foTemplate.write(pTemplate, 0, p_nSize);
            w_foTemplate.close();

            // Show Save Path
            m_strPost += "\nSaved file path = " + w_szSaveDirPath + "/" + String.valueOf(p_nUserID) + ".fpt";
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

        return true;
    }

    public boolean ReadImage(byte[] pImage, int p_nWidth, int p_nHeight) {
        if ((p_nWidth == 0) || (p_nHeight == 0))
            return false;

        System.arraycopy(m_binImage, 0, pImage, 0, p_nWidth * p_nHeight);

        return true;
    }

    Runnable runDrawImage = new Runnable() {
        public void run() {
            int nSize;

            MakeBMPBuf(m_binImage, m_bmpImage, m_nImgWidth, m_nImgHeight);

            if ((m_nImgWidth % 4) != 0)
                nSize = m_nImgWidth + (4 - (m_nImgWidth % 4));
            else
                nSize = m_nImgWidth;

            nSize = 1078 + nSize * m_nImgHeight;

            Bitmap image = BitmapFactory.decodeByteArray(m_bmpImage, 0, nSize);

            m_FpImageViewer.setImageBitmap(image);
        }
    };

    private void MakeBMPBuf(byte[] Input, byte[] Output, int iImageX, int iImageY) {

        byte[] w_bTemp = new byte[4];
        byte[] head = new byte[1078];
        byte[] head2 = {
                /***************************/
                //file header
                0x42, 0x4d,//file type
                //0x36,0x6c,0x01,0x00, //file size***
                0x0, 0x0, 0x0, 0x00, //file size***
                0x00, 0x00, //reserved
                0x00, 0x00,//reserved
                0x36, 0x4, 0x00, 0x00,//head byte***
                /***************************/
                //infoheader
                0x28, 0x00, 0x00, 0x00,//struct size

                //0x00,0x01,0x00,0x00,//map width***
                0x00, 0x00, 0x0, 0x00,//map width***
                //0x68,0x01,0x00,0x00,//map height***
                0x00, 0x00, 0x00, 0x00,//map height***

                0x01, 0x00,//must be 1
                0x08, 0x00,//color count***
                0x00, 0x00, 0x00, 0x00, //compression
                //0x00,0x68,0x01,0x00,//data size***
                0x00, 0x00, 0x00, 0x00,//data size***
                0x00, 0x00, 0x00, 0x00, //dpix
                0x00, 0x00, 0x00, 0x00, //dpiy
                0x00, 0x00, 0x00, 0x00,//color used
                0x00, 0x00, 0x00, 0x00,//color important
        };

        int i, j, num, iImageStep;

        Arrays.fill(w_bTemp, (byte) 0);

        System.arraycopy(head2, 0, head, 0, head2.length);

        if ((iImageX % 4) != 0)
            iImageStep = iImageX + (4 - (iImageX % 4));
        else
            iImageStep = iImageX;

        num = iImageX;
        head[18] = (byte) (num & (byte) 0xFF);
        num = num >> 8;
        head[19] = (byte) (num & (byte) 0xFF);
        num = num >> 8;
        head[20] = (byte) (num & (byte) 0xFF);
        num = num >> 8;
        head[21] = (byte) (num & (byte) 0xFF);

        num = iImageY;
        head[22] = (byte) (num & (byte) 0xFF);
        num = num >> 8;
        head[23] = (byte) (num & (byte) 0xFF);
        num = num >> 8;
        head[24] = (byte) (num & (byte) 0xFF);
        num = num >> 8;
        head[25] = (byte) (num & (byte) 0xFF);

        j = 0;
        for (i = 54; i < 1078; i = i + 4) {
            head[i] = head[i + 1] = head[i + 2] = (byte) j;
            head[i + 3] = 0;
            j++;
        }

        System.arraycopy(head, 0, Output, 0, 1078);

        if (iImageStep == iImageX) {
            for (i = 0; i < iImageY; i++) {
                System.arraycopy(Input, i * iImageX, Output, 1078 + i * iImageX, iImageX);
            }
        } else {
            iImageStep = iImageStep - iImageX;

            for (i = 0; i < iImageY; i++) {
                System.arraycopy(Input, i * iImageX, Output, 1078 + i * (iImageX + iImageStep), iImageX);
                System.arraycopy(w_bTemp, 0, Output, 1078 + i * (iImageX + iImageStep) + iImageX, iImageStep);
            }
        }
    }

    private void ProcResponsePacket(int p_nCode, int p_nRet, int p_nParam1, int p_nParam2) {
        m_strPost = "";
        m_txtStatus.setText(m_strPost);

        switch (p_nCode) {
            case (short) DevComm.CMD_ENROLL_CODE:
            case (short) DevComm.CMD_VERIFY_CODE:
            case (short) DevComm.CMD_IDENTIFY_CODE:
            case (short) DevComm.CMD_IDENTIFY_FREE_CODE:
            case (short) DevComm.CMD_ENROLL_ONETIME_CODE:
            case (short) DevComm.CMD_CHANGE_TEMPLATE_CODE:
            case (short) DevComm.CMD_VERIFY_WITH_DOWN_TMPL_CODE:
            case (short) DevComm.CMD_IDENTIFY_WITH_DOWN_TMPL_CODE:
            case (short) DevComm.CMD_VERIFY_WITH_IMAGE_CODE:
            case (short) DevComm.CMD_IDENTIFY_WITH_IMAGE_CODE:
                if (p_nRet == (short) DevComm.ERR_SUCCESS) {
                    switch (p_nParam1) {
                        case (short) DevComm.NEED_RELEASE_FINGER:
                            m_strPost = "Release your finger";
                            break;
                        case (short) DevComm.NEED_FIRST_SWEEP:
                            m_strPost = "Input your finger";
                            break;
                        case (short) DevComm.NEED_SECOND_SWEEP:
                            m_strPost = "Two More";
                            break;
                        case (short) DevComm.NEED_THIRD_SWEEP:
                            m_strPost = "One More";
                            break;
                        default:
                            m_strPost = String.format("Result : Success\r\nTemplate No : %d", p_nParam1);
                            if (p_nCode != DevComm.CMD_IDENTIFY_FREE_CODE)
                                EnableCtrl(true);
                            break;
                    }
                } else {
                    m_strPost = String.format("Result : Fail\r\n");
                    m_strPost += GetErrorMsg((short) p_nParam1);
                    if (HostLib.getInstance(this).FPDevComm().LOBYTE((short) p_nParam1) == DevComm.ERR_BAD_QUALITY) {
                        m_strPost += "\r\nAgain... !";
                    } else {
                        if (p_nParam1 == DevComm.ERR_DUPLICATION_ID) {
                            m_strPost += String.format(" %d.", p_nParam2);
                        } else if (p_nParam1 == DevComm.ERR_ALL_TMPL_EMPTY) {
                            EnableCtrl(true);
                        }
                    }
                    if (p_nCode != DevComm.CMD_IDENTIFY_FREE_CODE)
                        EnableCtrl(true);
                }
                break;

            case (short) DevComm.CMD_GET_EMPTY_ID_CODE:
                if (p_nRet == (short) DevComm.ERR_SUCCESS) {
                    m_strPost = String.format("Result : Success\r\nEmpty ID : %d", p_nParam1);
                } else {
                    m_strPost = String.format("Result : Fail\r\n");
                    m_strPost += GetErrorMsg((short) p_nParam1);
                }
                break;

            case (short) DevComm.CMD_GET_ENROLL_COUNT_CODE:
                if (p_nRet == (short) DevComm.ERR_SUCCESS) {
                    m_strPost = String.format("Result : Success\r\nEnroll Count : %d", p_nParam1);
                } else {
                    m_strPost = String.format("Result : Fail\r\n");
                    m_strPost += GetErrorMsg((short) p_nParam1);
                }
                break;

            case (short) DevComm.CMD_CLEAR_TEMPLATE_CODE:
                if (p_nRet == (short) DevComm.ERR_SUCCESS) {
                    m_strPost = String.format("Result : Success\r\nTemplate No : %d", p_nParam1);
                } else {
                    m_strPost = String.format("Result : Fail\r\n");
                    m_strPost += GetErrorMsg((short) p_nParam1);
                }
                break;

            case (short) DevComm.CMD_CLEAR_ALLTEMPLATE_CODE:
                if (p_nRet == (short) DevComm.ERR_SUCCESS) {
                    m_strPost = String.format("Result : Success\r\nCleared Template Count : %d", p_nParam1);
                } else {
                    m_strPost = String.format("Result : Fail\r\n");
                    m_strPost += GetErrorMsg((short) p_nParam1);
                }
                break;

            case (short) DevComm.CMD_READ_TEMPLATE_CODE:
                if (p_nRet == (short) DevComm.ERR_SUCCESS) {
                    m_strPost = String.format("Result : Success\r\nTemplate No : %d", p_nParam1);
                    WriteTemplateFile(p_nParam1, m_TemplateData, m_nTemplateSize);
                } else {
                    m_strPost = String.format("Result : Fail\r\n");
                    m_strPost += GetErrorMsg((short) p_nParam1);
                }
                break;

            case (short) DevComm.CMD_WRITE_TEMPLATE_CODE:
                if (p_nRet == (short) DevComm.ERR_SUCCESS) {
                    m_strPost = String.format("Result : Success\r\nTemplate No : %d", p_nParam1);
                } else {
                    m_strPost = String.format("Result : Fail\r\n");
                    m_strPost += GetErrorMsg((short) p_nParam1);

                    if (p_nParam1 == DevComm.ERR_DUPLICATION_ID) {
                        m_strPost += String.format(" %d.", p_nParam2);
                    }
                }
                break;

            case (short) DevComm.CMD_UP_IMAGE_CODE:
                if (p_nRet == (short) DevComm.ERR_SUCCESS) {
                    m_strPost = String.format("Result : Receive Image Success");
                    m_txtStatus.post(runDrawImage);
                } else {
                    m_strPost = String.format("Result : Fail\r\n");
                    m_strPost += GetErrorMsg((short) p_nParam1);
                }
                EnableCtrl(true);
                break;

            case (short) DevComm.CMD_GET_FW_VERSION_CODE:
                if (p_nRet == (short) DevComm.ERR_SUCCESS) {
                    m_strPost = String.format("Result : Success\r\nFirmware Version: %d.%d", HostLib.getInstance(this).FPDevComm().LOBYTE((short) p_nParam1), HostLib.getInstance(this).FPDevComm().HIBYTE((short) p_nParam1));
                } else {
                    m_strPost = String.format("Result : Fail\r\n");
                    m_strPost += GetErrorMsg((short) p_nParam1);
                }
                break;

            case (short) DevComm.CMD_VERIFY_DEVPASS_CODE:
            case (short) DevComm.CMD_SET_DEVPASS_CODE:
            case (short) DevComm.CMD_EXIT_DEVPASS_CODE:
                if (p_nRet == (short) DevComm.ERR_SUCCESS) {
                    m_strPost = String.format("Result : Success.");
                } else {
                    m_strPost = String.format("Result : Fail\r\n");
                    m_strPost += GetErrorMsg((short) p_nParam1);
                }
                break;

            case (short) DevComm.CMD_FEATURE_OF_CAPTURED_FP_CODE:
                if (p_nRet == (short) DevComm.ERR_SUCCESS) {
                    m_strPost = String.format("Result : Success");
                    //WriteTemplateFile(0, m_TemplateData, m_nTemplateSize);
                } else {
                    m_strPost = String.format("Result : Fail\r\n");
                    m_strPost += GetErrorMsg((short) p_nParam1);
                }
                EnableCtrl(true);
                break;

            case (short) DevComm.CMD_FP_CANCEL_CODE:
                if (p_nRet == (short) DevComm.ERR_SUCCESS) {
                    m_strPost = String.format("Result : FP Cancel Success.");
                } else {
                    m_strPost = String.format("Result : Fail\r\n");
                    m_strPost += GetErrorMsg((short) p_nParam1);
                }
                break;

            case (short) DevComm.CMD_GET_BROKEN_TEMPLATE_CODE:
                if (p_nRet == (short) DevComm.ERR_SUCCESS) {
                    m_strPost = String.format("Result : Success\r\nBroken Template Count : %d\r\nFirst Broken Template ID : %d", p_nParam1, p_nParam2);
                } else {
                    m_strPost = String.format("Result : Fail\r\n");
                    m_strPost += GetErrorMsg((short) p_nParam1);
                }
                break;

            case (short) DevComm.CMD_ADJUST_SENSOR_CODE:
                if (p_nRet == (short) DevComm.ERR_SUCCESS) {
                    m_strPost = String.format("Result : Adjust Success");
                } else {
                    m_strPost = String.format("Result : Fail\r\n");
                    m_strPost += GetErrorMsg((short) p_nParam1);
                }
                break;

            case (short) DevComm.CMD_ENTERSTANDBY_CODE:
                if (p_nRet == (short) DevComm.ERR_SUCCESS) {
                    m_strPost = String.format("Result : Enter Standby Mode Success");
                } else {
                    m_strPost = String.format("Result : Enter Standby Mode Fail\r\n");
                    m_strPost += GetErrorMsg((short) p_nParam1);
                }
                break;

            case (short) DevComm.CMD_FINGER_DETECT_CODE:
                if (p_nRet == (short) DevComm.ERR_SUCCESS) {
                    if (p_nParam1 == (short) HostLib.getInstance(this).FPDevComm().DETECT_FINGER) {
                        m_strPost = String.format("Finger Detected.");
                    } else if (p_nParam1 == (short) HostLib.getInstance(this).FPDevComm().NO_DETECT_FINGER) {
                        m_strPost = String.format("Finger not Detected.");
                    }
                } else {
                    m_strPost = String.format("Result : Fail\r\n");
                    m_strPost += GetErrorMsg((short) p_nParam1);
                }
                EnableCtrl(true);
                break;

            case (short) DevComm.CMD_IDENTIFY_TEMPLATE_WITH_FP_CODE:
                if (p_nRet == (short) DevComm.ERR_SUCCESS) {
                    if (HostLib.getInstance(this).FPDevComm().LOBYTE((short) p_nParam1) == (short) DevComm.DOWNLOAD_SUCCESS) {
                        m_strPost = String.format("Result : Download Success\r\nInput your finger");
                        m_txtStatus.setText(m_strPost);
                        return;
                    } else {
                        m_strPost = String.format("Result : Identify OK.");
                        m_txtStatus.setText(m_strPost);
                    }
                } else {
                    m_strPost = String.format("Result : Fail\r\n");
                    m_strPost += GetErrorMsg((short) p_nParam1);
                }
                break;

            case (short) DevComm.RCM_INCORRECT_COMMAND_CODE:
                m_strPost = String.format("Received incorrect command !");
                break;

            case (short) DevComm.CMD_ENTER_ISPMODE_CODE:
                if (p_nRet == (short) DevComm.ERR_SUCCESS) {
                    m_strPost = String.format("Result : Success\r\nRunning ISP. Can you programming.");
                } else {
                    m_strPost = String.format("Result : Fail\r\n");
                    m_strPost += GetErrorMsg((short) p_nParam1);
                }
                break;

            default:
                break;
        }

        m_txtStatus.setText(m_strPost);
    }

    private String GetErrorMsg(short p_wErrorCode) {
        String w_ErrMsg;
        switch (p_wErrorCode & 0xFF) {
            case DevComm.ERR_VERIFY:
                w_ErrMsg = "Verify NG";
                break;
            case DevComm.ERR_IDENTIFY:
                w_ErrMsg = "Identify NG";
                break;
            case DevComm.ERR_EMPTY_ID_NOEXIST:
                w_ErrMsg = "Empty Template no Exist";
                break;
            case DevComm.ERR_BROKEN_ID_NOEXIST:
                w_ErrMsg = "Broken Template no Exist";
                break;
            case DevComm.ERR_TMPL_NOT_EMPTY:
                w_ErrMsg = "Template of this ID Already Exist";
                break;
            case DevComm.ERR_TMPL_EMPTY:
                w_ErrMsg = "This Template is Already Empty";
                break;
            case DevComm.ERR_INVALID_TMPL_NO:
                w_ErrMsg = "Invalid Template No";
                break;
            case DevComm.ERR_ALL_TMPL_EMPTY:
                w_ErrMsg = "All Templates are Empty";
                break;
            case DevComm.ERR_INVALID_TMPL_DATA:
                w_ErrMsg = "Invalid Template Data";
                break;
            case DevComm.ERR_DUPLICATION_ID:
                w_ErrMsg = "Duplicated ID : ";
                break;
            case DevComm.ERR_BAD_QUALITY:
                w_ErrMsg = "Bad Quality Image";
                break;
            case DevComm.ERR_SMALL_LINES:
                w_ErrMsg = "Small line Image";
                break;
            case DevComm.ERR_TOO_FAST:
                w_ErrMsg = "Too fast swiping";
                break;
            case DevComm.ERR_TIME_OUT:
                w_ErrMsg = "Time Out";
                break;
            case DevComm.ERR_GENERALIZE:
                w_ErrMsg = "Fail to Generalize";
                break;
            case DevComm.ERR_NOT_AUTHORIZED:
                w_ErrMsg = "Device not authorized.";
                break;
            case DevComm.ERR_EXCEPTION:
                w_ErrMsg = "Exception Error ";
                break;
            case DevComm.ERR_MEMORY:
                w_ErrMsg = "Memory Error ";
                break;
            case DevComm.ERR_INVALID_PARAM:
                w_ErrMsg = "Invalid Parameter";
                break;
            case DevComm.ERR_NO_RELEASE:
                w_ErrMsg = "No Release Finger Fail";
                break;
            case DevComm.ERR_INTERNAL:
                w_ErrMsg = "Internal Error.";
                break;
            case DevComm.ERR_FP_CANCEL:
                w_ErrMsg = "Canceled.";
                break;
            case DevComm.ERR_INVALID_OPERATION_MODE:
                w_ErrMsg = "Invalid Operation Mode";
                break;
            case DevComm.ERR_NOT_SET_PWD:
                w_ErrMsg = "Password was not set.";
                break;
            case DevComm.ERR_FP_NOT_DETECTED:
                w_ErrMsg = "Finger is not detected.";
                break;
            case DevComm.ERR_ADJUST_SENSOR:
                w_ErrMsg = "Failed to adjust sensor.";
                break;
            default:
                w_ErrMsg = "Fail";
                break;

        }
        return w_ErrMsg;
    }
}
